public class Main {

    public static void main(String[] args) throws InterruptedException {
        printProgress(Style.STYLE1);
        printProgress(Style.STYLE2);
        printProgress(Style.STYLE3);
        printProgress(Style.STYLE4);
    }


    /**
     * 进度条总样式设计,具体参考{@link Style#Style(String, String, String, String, String, String, String, String, int) 构造函数};
     */
    enum Style {
        STYLE1("[", "=", ">", " ", "]", "(", ")", "%", 20),
        STYLE2("[", dyeing(Color.GREEN, "="), dyeing(Color.GREEN, ">"), " ", "]", "(", ")", "%", 20),
        STYLE3("[", "#", "#", "+", "]", "(", ")", "", 20),
        STYLE4("", "🤣", "👉", "+", "🤡", "(", ")", "", 20),
        ;


        //字符样式
        private final String s1, s2, s3, s4, s5, s6, s7, s8;
        //字符长度
        private final int len;

        /**
         * @param s1  参数1
         * @param s2  参数2
         * @param s3  参数3
         * @param s4  参数4
         * @param s5  参数5
         * @param s6  参数6
         * @param s7  参数7
         * @param s8  参数8
         * @param len 进度条长度
         */
        Style(String s1, String s2, String s3, String s4, String s5, String s6, String s7, String s8, int len) {
            this.s1 = s1;
            this.s2 = s2;
            this.s3 = s3;
            this.s4 = s4;
            this.s5 = s5;
            this.s6 = s6;
            this.s7 = s7;
            this.s8 = s8;
            this.len = len;
        }
    }


    /**
     * 字体染色
     *
     * @param color 颜色类型
     * @param msg   需要染色的文字
     * @return 染好色的文字
     */
    private static String dyeing(Color color, String msg) {
        String[] split = color.str.split(" ");
        return split[0] + msg + split[1];
    }


    /**
     * 颜色改变只作用在IDEA,其他没试过👀
     */
    enum Color {
        RED("\033[31m" + " " + "\033[m"),
        GREEN("\033[32m" + " " + "\033[m"),
        YELLOW("\033[33m" + " " + "\033[m"),
        BLUE("\033[34m" + " " + "\033[m"),
        PURPLE("\033[35m" + " " + "\033[m"),
        YOUNG("\033[36m" + " " + "\033[m"),
        GREY("\033[37m" + " " + "\033[m"),
        BACK_RED("\033[41m" + " " + "\033[m"),
        BACK_GREEN("\033[42m" + " " + "\033[m"),
        BACK_YELLOW("\033[43m" + " " + "\033[m"),
        BACK_BLUE("\033[44m" + " " + "\033[m"),
        BACK_PURPLE("\033[45m" + " " + "\033[m"),
        BACK_YOUNG("\033[46m" + " " + "\033[m"),
        BACK_GREY("\033[47m" + " " + "\033[m"),
        ;

        private final String str;

        /**
         * @param str 需要染色的字符串
         */
        Color(String str) {
            this.str = str;
        }
    }


    /**
     * 进度条输出(演示)
     *
     * @param style 进度条{@link Style 样式}
     */
    private static void printProgress(Style style) throws InterruptedException {
        //遍历进度条总长度
        for (int i = 1; i <= style.len; i++) {
            //输出框
            System.out.print(style.s1);
            for (int j = 1; j <= i; j++) {
                System.out.print(style.s2);
                if (j == i) {
                    System.out.print(i == style.len ? style.s2 : style.s3);
                }
            }
            //填充空格
            for (int j = 1; j <= style.len - i; j++) {
                System.out.print(style.s4);
            }
            //输出当前进度
            System.out.printf(style.s5 + " " + style.s6 + "%.1f%s" + style.s7, (i * 1.000 / style.len) * 100, style.s8);
            Thread.sleep(200);
            System.out.print("\r");

        }
    }


    /**
     * 进度条输出
     *
     * @param num   当前进度
     * @param style 进度条样式
     */
    private static void printProgress(double num, Style style) {
        //限制最大进度量
        num = Math.min(num, style.len);
        System.out.print(style.s1);
        //输出内容
        for (int i = 1; i <= num; i++) {
            System.out.print(style.s2);
            if (i == num) {
                System.out.print(style.len == num ? style.s2 : style.s3);
            }
        }
        //输出后续填充
        for (int i = 1; i <= style.len - num; i++) {
            System.out.print(style.s4);
        }
        //后续收尾以及总进度显示
        System.out.printf(style.s5 + " " + style.s6 + "%.1f%s" + style.s7, (num / style.len) * 100, style.s8);
        System.out.print("\r");

    }
}